/**
 * 
 */
package cn.springsoter.core.xxljob.config;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;

import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import com.xxl.job.core.handler.IJobHandler;

import cn.springsoter.core.xxljob.annontation.XxlJobHandler;
import lombok.extern.slf4j.Slf4j;

/**
 * @author kevin
 * @Description 扫描所有类形式 job ，统一注册到 xxl-job
 * 必须开启配置，才会进行装配
 */
@Slf4j
@ConditionalOnProperty(prefix = "xxl.job", name = "enable", havingValue = "true")
@Configuration
public class XxlRegistJobHandlerConfig {

    /*
     * 注入所有实现了 IJobHandler 的类
     */
    @Autowired(required = false)
    private List<IJobHandler> jobHandlerList;

    @PostConstruct
    private void init() {
        if (CollectionUtils.isEmpty(jobHandlerList)) {
            log.warn("在Spring容器中没有检测到Job对象，请确保Job对象实现IJobHandler接口，并且应用了@XxlJobHandler注解");
            return;
        }

        scanRegistJobHandler();
    }

    /**
     * 扫描并注册
     */
    private void scanRegistJobHandler() {
        //防止jobHandler名称重复
        Set<String> jobNames = new HashSet<>();

        jobHandlerList.stream().filter(job -> {
            boolean implementsSimpleJob = IJobHandler.class.isAssignableFrom(job.getClass());
            boolean hasJobDefine = job.getClass().getAnnotation(XxlJobHandler.class) != null;
            return implementsSimpleJob && hasJobDefine;
        }).forEach(job -> {
            XxlJobHandler def = job.getClass().getAnnotation(XxlJobHandler.class);
            final String value = def.value();
            if (jobNames.contains(value)) {
                throw new RuntimeException("定时任务名重复注册，任务job名："+value);
            }
            jobNames.add(value);
            XxlJobSpringExecutor.registJobHandler(value, job);
        });
    }
}

